import React from 'react';
import { message, Spin } from 'antd';
import { DrawerForm, ProFormText } from '@ant-design/pro-form';
import CheckGroupList from './components/CheckGroupList';
import type { AdminGroupTree, AdminGroupItem } from '@/services/system/admin';
import {
  getAdminGroupTree,
  updateAdminGroup,
  getAdminGroupById,
  existGroupName,
} from '@/services/system/admin';
import { drawerProps } from '@/services/Common';

type AdminGroupEditProps = API.EditPageProps;

/**
 * 根据一级path，得到这个path下的被选中的菜单
 * @param rootPath
 * @param allCheckedList
 */
const getDefaultCheckList = (rootPath: string, allCheckedList: AdminGroupTree[]) => {
  for (let i = 0; i < allCheckedList.length; i += 1) {
    if (rootPath === allCheckedList[i].path) {
      return allCheckedList[i].children;
    }
  }
  return [];
};

const AdminGroupEdit: React.FC<AdminGroupEditProps> = (props: AdminGroupEditProps) => {
  const { visible, id, setVisible, listReload } = props;
  const groupId = id as number;

  // 保存在ref中，这样比usestate好，因为usestate会刷新页面
  const checkedStore = React.useRef<AdminGroupTree[]>([]);

  // 从数据库中得到，用来刷新页面的数据
  const [adminGroup, setAdminGroup] = React.useState<API.AdminGroup | null>(null);
  const [adminGroupTree, setAdminGroupTree] = React.useState<AdminGroupTree[]>([]);

  // 读取取数据库中的数据，并刷新页面
  React.useEffect(() => {
    if (groupId > 0) {
      getAdminGroupById(groupId).then((result) => {
        if (result?.data) {
          checkedStore.current = JSON.parse(result.data.limits ? result.data.limits : '[]');
          setAdminGroup(result.data);
        }
      });
    } else {
      const defalutChecked =
        '[{"cname":"总览","path":"/welcome","children":[{"cname":"首页","path":"/welcome/home"}]}]';
      checkedStore.current = JSON.parse(defalutChecked);
      setAdminGroup({
        groupId,
        groupName: '',
        limits: defalutChecked,
      });
    }

    getAdminGroupTree().then((result) => {
      if (result?.data) {
        setAdminGroupTree(result?.data);
      }
    });
  }, []);

  /**
   * 被子组件调用，用来保存选中的菜单
   * @param rootPath
   * @param checked
   */
  const callback = (cname: string, rootPath: string, checked: AdminGroupItem[]) => {
    for (let i = 0; i < checkedStore.current.length; i += 1) {
      if (checkedStore.current[i].path === rootPath) {
        if (checked.length > 0) {
          checkedStore.current[i].children = checked;
        } else {
          // 如果子菜单为空，那么就删除这个
          checkedStore.current.splice(i, 1);
        }
        return;
      }
    }
    checkedStore.current.push({
      cname,
      path: rootPath,
      children: checked,
    });
  };

  /**
   * 保存事件
   * @param values 表单传递过来的参数
   */
  const onFinishHandle = async (values: Record<string, any>) => {
    const ren: API.ResponseInfo<number> = await updateAdminGroup({
      groupId,
      groupName: values.groupName,
      limits: JSON.stringify(checkedStore.current),
    });
    if (ren.success) {
      // List要刷新
      listReload();
      message.success('提交成功');
      // 不返回不会关闭弹框
      return true;
    }
    message.success('保存失败');
    return false;
  };

  /**
   * 为了调用List页面的方法，让这个页面关闭。
   * @param visibled 点击关闭按钮，确认按钮，等按钮后传递过来的数值
   */
  const onVisibleChangeHandle = (visibled: boolean) => {
    if (!visibled) {
      setVisible(false);
    }
  };

  const groupNameValidator = async (_: unknown, value: any) => {
    const result = await existGroupName(value, groupId);
    if (result.data) {
      return Promise.reject(new Error('权限组名称重复'));
    }
    return Promise.resolve();
  };

  return (
    <DrawerForm
      title={groupId > 0 ? '编辑权限组' : '新增权限组'}
      visible={visible}
      drawerProps={drawerProps}
      onVisibleChange={onVisibleChangeHandle}
      onFinish={onFinishHandle}
    >
      {/* 只有当adminGroup与adminGroupTree都从数据库中得到后才刷新页面 */}
      {adminGroup && adminGroupTree.length > 0 ? (
        <>
          <ProFormText
            width="md"
            name="groupName"
            label="权限组名称"
            placeholder="请输入名称"
            initialValue={adminGroup.groupName}
            rules={[
              {
                required: true,
              },
              {
                validator: groupNameValidator,
                validateTrigger: ['onBlur'],
              },
            ]}
          />
          {adminGroupTree.map((item) => {
            return (
              <CheckGroupList
                key={item.path}
                rootPath={item.path}
                rootCName={item.cname ? item.cname : ''}
                callBack={callback}
                options={item.children}
                defaultChecked={getDefaultCheckList(item.path, checkedStore.current)}
              />
            );
          })}
        </>
      ) : (
        <Spin tip="Loading..." />
      )}
    </DrawerForm>
  );
};

export default AdminGroupEdit;
